<?php
/**
 * Created by PhpStorm.
 * User: zyh
 * Date: 2018/5/29
 * Time: 下午8:27
 */

namespace app\admin\model;


use app\index\command\Events;
use GatewayClient\Gateway;
use think\Cache;
use think\console\Output;
use think\Db;
use think\Exception;
use think\Model;

class Rewards extends Model
{
    /**
     * @var 需要处理的方向  投注过大 需要减少的方向
     */
    private $oper = 1;

    //获取投注合计信息
    public function getRewardsInfo($gid)
    {
        $game = null;
        if ($gid == null) {
            //如果没有iD就选择最后一个比赛  最后一个比赛发给客户端
            $game = Game::get(function ($query) {
                $query->order('id', 'desc');
            });
            $gid = $game['id'];
        } else {
            $game = Game::get($gid);
        }


        $data = [];
        //基本统计数据
        $data['id'] = $gid;
        $data['status'] = $game['status'];

        $data['red_reward'] = $this->where(['direction' => 1, "gid" => $gid])->sum("reward");
        $data['red_total'] = $this->where(['direction' => 1, "gid" => $gid])->sum("reward");
        $data['blue_reward'] = $this->where(['direction' => 2, "gid" => $gid])->sum("reward");
        $data['blue_total'] = $this->where(['direction' => 2, "gid" => $gid])->sum("reward");
        //平台
        $data['system'] = $this->where(['direction' => 0, "gid" => $gid])->sum('reward');

        $info_data = [];
        //红方详细


        $info_data['red_kaipen'] = $this->where(['kid' => 10, 'direction' => 1, "gid" => $gid])->sum('reward');
        $info_data['red_qikou'] = $this->where(['kid' => 7, 'direction' => 1, "gid" => $gid])->sum('reward');
        $info_data['red_liukou'] = $this->where(['kid' => 6, 'direction' => 1, "gid" => $gid])->sum('reward');
        $info_data['red_wukou'] = $this->where(['kid' => 5, 'direction' => 1, "gid" => $gid])->sum('reward');
        $info_data['red_sikou'] = $this->where(['kid' => 4, 'direction' => 1, "gid" => $gid])->sum('reward');

        //蓝方详细
        $info_data['blue_kaipen'] = $this->where(['kid' => 10, 'direction' => 2, "gid" => $gid])->sum('reward');
        $info_data['blue_qikou'] = $this->where(['kid' => 7, 'direction' => 2, "gid" => $gid])->sum('reward');
        $info_data['blue_liukou'] = $this->where(['kid' => 6, 'direction' => 2, "gid" => $gid])->sum('reward');
        $info_data['blue_wukou'] = $this->where(['kid' => 5, 'direction' => 2, "gid" => $gid])->sum('reward');
        $info_data['blue_sikou'] = $this->where(['kid' => 4, 'direction' => 2, "gid" => $gid])->sum('reward');
        //计算扣位
        if ($game['status'] <= 1) {
            $data['kou'] = 0;//false
        } else {
            //两边相等时取最后一次扣位 保持不变
            if ($info_data['red_kaipen'] > $info_data['blue_kaipen']) {
                $data['kou'] = 1;
            } elseif ($info_data['red_kaipen'] < $info_data['blue_kaipen']) {
                $data['kou'] = 2;
            } elseif ($info_data['red_kaipen'] == $info_data['blue_kaipen']) {
                $data['kou'] = Cache::get('kou', false);
            }
            Cache::set('kou', $data['kou']);
        }

        $data['info'] = $info_data;
        $data['winners'] = Cache::get("winners");
        return $data;
    }

    //根据当前阶段，重新计算其他阶段的显示分
    public function formatData($status, $kid)
    {
        //当前阶段

    }

    //新增投注信息
    public function insertReward($data)
    {
        $user_score = User::get($data['uid'])['score'];

        $reward_score = $this->calToScore($data['reward'], $data['kid'], $data['direction'], $data['kou']);

        //余额不足
        if ($user_score < $reward_score) return false;
        //扣除用户余额 并且记录信息
        //reward_1000_1_10
        Cache::inc("reward_" . $data['gid'] . "_" . $data['uid'] . "_" . $data['kid'], $reward_score);
        User::get($data['uid'])->setDec('score', $reward_score);
        $jie = $data['kid'] == 10 ? "平花" : $data['kid'] . "扣";
        $userhis = new Userhis();
        $userhis->save([
            'gid' => $data['gid'],
            'uid' => $data['uid'],
            'data' => 0 - $reward_score,
            'create_time' => date("Y-m-d H:i:s"),
            'comment' => $jie . "阶段扣除投注分"
        ]);
        return $this->save($data);
    }


    /**
     * @name  结算上一个结算的全部数据 和踢出
     * @param null $winner
     * @return int|mixed|null
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */

    public function settlement($gid, $status, $winner = null)
    {
        $output = new Output();
        $output->writeln("状态变更开始...");

        //双方未结算的全部信息
        $red_reward = $this->where(['status' => 0, 'direction' => 1, "gid" => $gid])->sum('reward');
        $blue_reward = $this->where(['status' => 0, 'direction' => 2, "gid" => $gid])->sum('reward');

        //当前要处理的阶段
        $phase = $this->where(['status' => 0])->order(['id' => 'desc'])->find()['kid'];
        if (!$phase) return null;//已经没有需要处理的了  但是剩下还需要结算

        //todo 不需要转换  只需要在一开始  只需要让两边对平 用户在提交的时候按照不同的金额计算
        $kou = $this->where(['status' => 0])->find()['kou'];

        if (($sub = $red_reward - $blue_reward) != 0) {
            //取得双方差值  从后到前处理订单 处理踢出
            $sub > 0 ? $this->oper = 1 : $this->oper = 2;
            $dec = abs($sub);

            //开始处理其中一方超出部分
            $rs = $this->where(['status' => 0, 'gid' => $gid])->order(['create_time' => 'desc'])->select(); //本次所有待处理订单

            try {
                Db::startTrans();
                foreach ($rs as $key => $value) {

                    if ($this->oper == $value['direction'] && $dec != 0) { //当前记录属于需要处理
                        //放扣 不需要转换倍数
                        if ($dec < $value['reward']) {
                            $value['reward'] = $value['reward'] - $dec;
                            $value['kill_reward'] = $dec;
                            $usrscore = $dec;
                            $dec = 0;
                        } else {
                            $value['kill_reward'] = $value['reward'];
                            $usrscore = $value['reward'];
                            $dec -= $value['reward'];
                            $value['reward'] = 0;//!!!
                        }

                        $return_score = $this->calToScore($usrscore, $value['kid'], $value['direction'], $value['kou']);
                        Cache::dec("reward_" . $value['gid'] . "_" . $value['uid'] . "_" . $value['kid'], $return_score);//记录剪掉
                        if ($value['kid'] == 10) {
                            $comment = "平花阶段踢出返还账户:" . $usrscore;
                        } else {
                            $comment = $value['kid'] . "扣阶段踢出返还账户:" . $return_score;
                        }

                        //踢出返还在踢出的时候就操作
                        $userhis = new Userhis();

                        $userhis->save([
                            'gid' => $gid,
                            'uid' => $value['uid'],
                            'data' => $return_score,
                            'create_time' => date("Y-m-d H:i:s"),
                            'comment' => $comment
                        ]);

                        User::get($value['uid'])->setInc('score', $return_score);
                        //通知用户刷新余额
                        $s = [];
                        $s['type'] = "score_update";
                        $s['data'] = User::get($value['uid'])['score'];
                        $s['his'] = $this->userGameReward($value['uid']);//用户当前的投注记录总额
                        Events::sendToUid($value['uid'], json_encode($s));
                    }
                    $value['status'] = 1;
                    $value->save();

                }
                Db::commit();
            } catch (Exception $e) {
                Db::rollback();
                return false;
            }
            $output->writeln("踢出处理完成");
        }

        //平花 还需确定扣方
        if ($phase == 10) {
            Cache::set('kou', $this->oper);
        }
        $output->writeln("比赛状态变更结束...踢出操作完成");
        //比赛状态变更结束

        if ($winner != null) {
            return $this->settle($gid, $winner);
        } else {
            $r = Game::get($gid)->save(['status' => $status]);
            return boolval($r);
        }
    }


    /**
     * @param $gid  比赛ID
     * @param $winner 胜方
     * @return int
     */
    public function settle($gid, $winner)
    {
        $output = new Output();
        $this->setWinCache($winner);
        $output->writeln("本局结算开始...");
        //参与的玩家
        $players = $this->where(['gid' => $gid])->distinct(true)->field('uid')->select();


        try{
            Db::startTrans();
            foreach ($players as $v) {
                $kou = [10, 7, 6, 5, 4];
                $wintotal = 0;
                $losetotal = 0;
                $taxtotle = 0;
                $data = 0;//信息记录
                foreach ($kou as $v1) {
                    //每扣投注
                    //该用户所有本阶段投注
                    $rewards = $this->where(['uid' => $v['uid'], 'gid' => $gid, 'kid' => $v1])->select();
                    //逐条处理每条记录输赢
                    foreach ($rewards as $id => $reward) {
                        if ($reward['reward'] == 0) continue;
                        $win = 0;
                        $lose = 0;
                        $winscore = 0;
                        //首选计算输赢 所有投注了胜方的都要赢
                        if ($winner == 0) {
                            $comment = "平局投注返回";
                            $lcoal_score = $this->calToScore($reward['reward'], $reward['kid'], $reward['direction'], $reward['kou']);
                            $user = new User();
                            $data = $lcoal_score;//用来记录日志的
                            $user::get($v['uid'])->setInc('score', $lcoal_score);
                        } else {
                            if ($reward['direction'] == $winner) {   //赢
                                $win = $this->winToScore($reward['reward'], $reward['kid'], $reward['direction'], $reward['kou']);
                                $comment = $reward['kid'] == 10 ? "平花阶段投注赢取" : $reward['kid'] . "扣阶段-接扣-投注赢取";
                                $data = $win;
                            } else {                      //输
                                $lose = $this->calToScore($reward['reward'], $reward['kid'], $reward['direction'], $reward['kou']);
                                $comment = $reward['kid'] == 10 ? $reward['kid'] . "扣阶段-放扣-投注输掉" : $reward['kid'] . "扣阶段-接扣-投注输掉";
                                $data = 0 - $lose;
                            }
                        }

                        //再分别计算赢的具体数值
                        $reward->win = $win;
                        $reward->lose = $lose;
                        $reward->tax = $win * 0.1;
                        $reward->save();

                        //用户赢取 = 投注本金 + 赢取 - 手续费

                        if ($win > 0) {
                            //给用户充值
                            echo "用户结算上分：本金" . $win . ",赢取：" . $win * 0.9 . "data:" . $data . "\r\n";
                            //用户本金
                            $lcoal_score = $this->calToScore($reward['reward'], $reward['kid'], $reward['direction'], $reward['kou']);
                            $user = new User();
                            $user::get($v['uid'])->setInc('score', $lcoal_score + $win * 0.9);
                            echo $user->getLastSql();
                        }
                        //todo 用户日志构造函数应该简化
                        $userhis = new Userhis();
                        $userhis->save([
                            'gid' => $gid,
                            'uid' => $v['uid'],
                            'data' => $data,
                            'create_time' => date("Y-m-d H:i:s"),
                            'comment' => $comment
                        ]);
                        $wintotal += $win;
                        $losetotal += $lose;
                        $taxtotle += $reward->tax;
                    }
                }
                $output->writeln("单用户扣阶段全部处理完毕...");
                //记录本场比赛输赢
                $record = new Record();
                $record->save([
                    'gid' => $gid,
                    'uid' => $v['uid'],
                    'win' => $wintotal,
                    'lose' => $losetotal,
                    'tax' => $taxtotle,
                    'create_time' => date("Y-m:d H:i:s")
                ]);

                //todo 对全部参与的用户发送结算信息  会不会造成并发量过大
                $info = $this->getResult($gid, $v['uid']);
                $result['data'] = $info;
                $result['winner'] = $winner;
                $result['type'] = "result";
                $result['status'] = -1;
                $result['winners'] = Cache::get("winners");
                Events::sendToUid($v['uid'], json_encode($result));
                $this->clearCache($gid,$v['uid']);
                //通知刷新余额
                $s = [];
                $s['type'] = "score_update";
                $s['data'] = User::get($v['uid'])['score'];
                $s['his'] = $this->userGameReward($v['uid']);
                Events::sendToUid($v['uid'], json_encode($s));
            }
            Game::get($gid)->save(['status'=>-1]);
            $gamedata = [];
            $gamedata['status'] = -1;
            $gamedata['winner'] = $winner;
            $gamedata['end_time'] = date("Y-m-d H:i:s");
            Game::get($gid)->save($gamedata);
            Db::commit();
        }catch (Exception $e){
            Db::rollback();
            return false;
        }

        $output->writeln("所有用户结算处理完成...");
        return true;
    }

    /**
     * 获取一个用户  某场比赛的战报
     * @param $gid
     * @param $uid
     * @return mixed
     */
    public function getResult($gid, $uid)
    {
        $info['kaipen_reward'] = $this->where(['gid' => $gid, 'uid' => $uid, 'kid' => 10])->sum('reward');
        $info['kaipen_kill_reward'] = $this->where(['gid' => $gid, 'uid' => $uid, 'kid' => 10])->sum('kill_reward');
        $info['kaipen_win'] = $this->where(['gid' => $gid, 'uid' => $uid, 'kid' => 10])->sum('win');
        $info['kaipen_tax'] = $this->where(['gid' => $gid, 'uid' => $uid, 'kid' => 10])->sum('tax');
        $info['kaipen_win'] = $info['kaipen_win'] - $info['kaipen_tax'];

        $info['qikou_reward'] = $this->where(['gid' => $gid, 'uid' => $uid, 'kid' => 7])->sum('reward');
        $info['qikou_kill_reward'] = $this->where(['gid' => $gid, 'uid' => $uid, 'kid' => 7])->sum('kill_reward');
        $info['qikou_win'] = $this->where(['gid' => $gid, 'uid' => $uid, 'kid' => 7])->sum('win');
        $info['qikou_tax'] = $this->where(['gid' => $gid, 'uid' => $uid, 'kid' => 7])->sum('tax');
        $info['qikou_win'] = $info['qikou_win'] - $info['qikou_tax'];

        $info['liukou_reward'] = $this->where(['gid' => $gid, 'uid' => $uid, 'kid' => 6])->sum('reward');
        $info['liukou_kill_reward'] = $this->where(['gid' => $gid, 'uid' => $uid, 'kid' => 6])->sum('kill_reward');
        $info['liukou_win'] = $this->where(['gid' => $gid, 'uid' => $uid, 'kid' => 6])->sum('win');
        $info['liukou_tax'] = $this->where(['gid' => $gid, 'uid' => $uid, 'kid' => 6])->sum('tax');
        $info['liukou_win'] = $info['liukou_win'] - $info['liukou_tax'];

        $info['wukou_reward'] = $this->where(['gid' => $gid, 'uid' => $uid, 'kid' => 5])->sum('reward');
        $info['wukou_kill_reward'] = $this->where(['gid' => $gid, 'uid' => $uid, 'kid' => 5])->sum('kill_reward');
        $info['wukou_win'] = $this->where(['gid' => $gid, 'uid' => $uid, 'kid' => 5])->sum('win');
        $info['wukou_tax'] = $this->where(['gid' => $gid, 'uid' => $uid, 'kid' => 5])->sum('tax');
        $info['wukou_win'] = $info['wukou_win'] - $info['wukou_tax'];

        $info['sikou_reward'] = $this->where(['gid' => $gid, 'uid' => $uid, 'kid' => 4])->sum('reward');
        $info['sikou_kill_reward'] = $this->where(['gid' => $gid, 'uid' => $uid, 'kid' => 4])->sum('kill_reward');
        $info['sikou_win'] = $this->where(['gid' => $gid, 'uid' => $uid, 'kid' => 4])->sum('win');
        $info['sikou_tax'] = $this->where(['gid' => $gid, 'uid' => $uid, 'kid' => 4])->sum('tax');
        $info['sikou_win'] = $info['sikou_win'] - $info['sikou_tax'];


        return $info;
    }

    /**
     * 将比赛结果存入缓存  今日胜负记录表
     * @param $winner
     * @version
     */
    public function setWinCache($winner)
    {
        $output = new Output();
        $winners = Cache::get("winners", []);
        //取出最后一个 重新插入最后一个结果
        $winners[count($winners) - 1] = $winner;
        Cache::set("winners", $winners);
        Cache::inc("gametotal");
    }

    /**
     * 把一个投注分数 转换为鲜花数  本身份扣款调用  用于扣花
     * @param $reward          投注数
     * @param $kid             投注阶段
     * @param int $direction 投注方向
     * @param int $kou 当前放扣方 默认1
     * @version   valToScore  将一个reward数据，转换为鲜花数量。用于处理  1、数据阶段  2、用户返还
     * @return 投注数|float|int
     */
    public function calToScore($reward, $kid, $direction = 1, $kou = 1)
    {
        $score = 0;
        //放扣
        if ($direction == $kou) {
            if ($kid == 10) {
                $score = $reward;
            } else {
                $score = $reward * 10;
            }
        } else {
            //接口
            if ($kid == 10) {
                $score = $reward;
            } else {
                $score = $reward * $kid;
            }
        }
        return $score;
    }

    /**
     * 把一个投注分数 转换为鲜花数    在赢的时候调用 把自己的投注数 转换为赢取的鲜花数
     * @param $reward
     * @param $kid
     * @param $direction
     * @param $kou
     * @return float|int
     */
    public function winToScore($reward, $kid, $direction, $kou)
    {
        $score = 0;
        //放扣
        if ($direction == $kou) {
            if ($kid == 10) {
                $score = $reward;
            } else {
                $score = $reward * $kid; // 10 * 7
            }
        } else {
            if ($kid == 10) {
                $score = $reward;
            } else {
                $score = $reward * 10;  // 10 * 10
            }
        }
        return $score;
    }


    /**
     * 获取用户当前场次里  投注的总额
     * @param $uid
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function userGameReward($uid)
    {
        $game = new Game();
        $gid = $game->order(['id' => 'desc'])->find()['id'];
        $data['kaipen'] = Cache::get("reward_" . $gid . "_" . $uid . "_10", 0);
        $data['qikou'] = Cache::get("reward_" . $gid . "_" . $uid . "_7", 0);
        $data['liukou'] = Cache::get("reward_" . $gid . "_" . $uid . "_6", 0);
        $data['wukou'] = Cache::get("reward_" . $gid . "_" . $uid . "_5", 0);
        $data['sikou'] = Cache::get("reward_" . $gid . "_" . $uid . "_4", 0);
        return $data;
    }


    /**
     * @param $gid
     * @param $uid
     */
    public function clearCache($gid,$uid)
    {
        //清除保存的扣
        Cache::rm("kou");
        //清除用户投注记录
        Cache::rm("reward_" . $gid . "_" . $uid . "_10");
        Cache::rm("reward_" . $gid . "_" . $uid . "_7");
        Cache::rm("reward_" . $gid . "_" . $uid . "_6");
        Cache::rm("reward_" . $gid . "_" . $uid . "_5");
        Cache::rm("reward_" . $gid . "_" . $uid . "_4");
    }
}